-
Notifications
You must be signed in to change notification settings - Fork 1.3k
api/server: support deploy-as-is template as VNF template #12499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 4.20
Are you sure you want to change the base?
api/server: support deploy-as-is template as VNF template #12499
Conversation
|
@blueorangutan package |
|
@weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
Codecov Report✅ All modified and coverable lines are covered by tests.
Additional details and impacted files@@ Coverage Diff @@
## 4.20 #12499 +/- ##
=============================================
- Coverage 17.10% 4.03% -13.08%
=============================================
Files 5255 402 -4853
Lines 466415 32721 -433694
Branches 54746 5832 -48914
=============================================
- Hits 79763 1319 -78444
+ Misses 377768 31247 -346521
+ Partials 8884 155 -8729
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
DaanHoogland
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clgtm, one (dumb luser) question .
| if (registerCmd.isDeployAsIs() && CollectionUtils.isNotEmpty(registerCmd.getVnfNics())) { | ||
| throw new InvalidParameterValueException("VNF Template cannot be registered with VNF nics as Template settings are read from OVA."); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want this always to be true? I could imagine a VNF getting a default gateway… Probably my lack of knowledge. I hope this is in the documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (registerCmd.isDeployAsIs() && CollectionUtils.isNotEmpty(registerCmd.getVnfNics())) { | |
| throw new InvalidParameterValueException("VNF Template cannot be registered with VNF nics as Template settings are read from OVA."); | |
| } | |
| if (registerCmd.isDeployAsIs() && CollectionUtils.isNotEmpty(registerCmd.getVnfNics())) { | |
| throw new InvalidParameterValueException("VNF nics cannot be specified when register a deploy-as-is Template. Please wait until Template settings are read from OVA."); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it clear now ? @DaanHoogland
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for deploying VNF appliances using deploy-as-is templates (OVA files) by allowing the VNF template functionality to work with templates that have network configurations already defined in the OVA. Previously, deploying such templates failed with "VNF nics list is empty" error.
Changes:
- Added conditional validation logic to handle both regular VNF templates (using
networkIdslist) and deploy-as-is VNF templates (usingvmNetworkMap) - Modified UI to disable network selection when deploy-as-is template networks are pre-configured
- Added validation to prevent registering/updating VNF nics on deploy-as-is templates since settings are read from the OVA
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/src/views/compute/wizard/VnfNicsSelection.vue | Adds templateNics prop and disables network selection for deploy-as-is templates |
| ui/src/views/compute/DeployVnfAppliance.vue | Passes templateNics to VnfNicsSelection component and updates validation logic to handle deploy-as-is template networks |
| api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManager.java | Adds new interface method validateVnfApplianceNetworksMap for deploy-as-is template validation |
| server/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManagerImpl.java | Implements validateVnfApplianceNetworksMap and adds check to prevent VNF nics on deploy-as-is templates |
| api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateUtils.java | Adds validation methods for deploy-as-is templates: prevents VNF nics registration and validates OVF networks |
| server/src/main/java/com/cloud/vm/UserVmManagerImpl.java | Routes to appropriate validation method based on whether template is deploy-as-is |
| server/src/main/java/com/cloud/template/TemplateManagerImpl.java | Adds validation for VNF nics updates on deploy-as-is templates using OVF network data |
| server/src/test/java/com/cloud/template/TemplateManagerImplTest.java | Adds mock bean for TemplateDeployAsIsDetailsDao to support new validation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (vnfNic.getDeviceId() < ovfNetworks.size() && !vnfNic.isRequired()) { | ||
| throw new InvalidParameterValueException(String.format("The VNF nic [device ID: %s ] is required as it is defined in the OVA template.", vnfNic.getDeviceId())); | ||
| } |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The validation logic has a flaw. It checks if vnfNic.getDeviceId() < ovfNetworks.size() && !vnfNic.isRequired(), which throws an error if the vnfNic is NOT required. This is backwards - the error message says "The VNF nic [device ID: %s ] is required" but the condition checks !vnfNic.isRequired(). The logic should be: if the device ID corresponds to an OVF network, the VNF nic MUST be required. So the condition should be checking if it's defined in OVF but marked as not required in the VNF configuration.
server/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManagerImpl.java
Show resolved
Hide resolved
| @Override | ||
| public void validateVnfApplianceNetworksMap(VirtualMachineTemplate template, Map<Integer, Long> vmNetworkMap) { | ||
| if (MapUtils.isEmpty(vmNetworkMap)) { | ||
| throw new InvalidParameterValueException("VNF networks map is empty"); | ||
| } | ||
| List<VnfTemplateNicVO> vnfNics = vnfTemplateNicDao.listByTemplateId(template.getId()); | ||
| for (VnfTemplateNicVO vnfNic : vnfNics) { | ||
| if (vnfNic.isRequired() && vmNetworkMap.size() <= vnfNic.getDeviceId()) { | ||
| throw new InvalidParameterValueException("VNF nic is required but not found: " + vnfNic); | ||
| } | ||
| } | ||
| } |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new method validateVnfApplianceNetworksMap is not covered by any unit tests. Since this is a critical validation method for deploy-as-is VNF templates and similar validation methods in the codebase have test coverage, unit tests should be added to verify the validation logic works correctly.
| public static void validateDeployAsIsTemplateVnfNics(List<OVFNetworkTO> ovfNetworks, List<VNF.VnfNic> vnfNics) { | ||
| if (CollectionUtils.isEmpty(vnfNics)) { | ||
| return; | ||
| } | ||
| if (CollectionUtils.isEmpty(ovfNetworks)) { | ||
| throw new InvalidParameterValueException("The list of networks read from OVA is empty. Please wait until the template is fully downloaded and processed."); | ||
| } | ||
| for (VNF.VnfNic vnfNic : vnfNics) { | ||
| if (vnfNic.getDeviceId() < ovfNetworks.size() && !vnfNic.isRequired()) { | ||
| throw new InvalidParameterValueException(String.format("The VNF nic [device ID: %s ] is required as it is defined in the OVA template.", vnfNic.getDeviceId())); | ||
| } | ||
| } | ||
| } |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new method validateDeployAsIsTemplateVnfNics is not covered by any unit tests. This is a new validation method for deploy-as-is VNF templates, and given that similar validation methods in the codebase have test coverage, unit tests should be added to ensure the validation logic works as expected.
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 16480 |
server/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManagerImpl.java
Show resolved
Hide resolved
| if (cmd instanceof UpdateVnfTemplateCmd) { | ||
| VnfTemplateUtils.validateApiCommandParams(cmd, template); | ||
| UpdateVnfTemplateCmd updateCmd = (UpdateVnfTemplateCmd) cmd; | ||
| if (template.isDeployAsIs() && CollectionUtils.isNotEmpty(updateCmd.getVnfNics())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this parameter allowed on update but not on VM creation? (https://github.com/apache/cloudstack/pull/12499/files#diff-f5ab861d900497f6f7c83d03a840a7994f407c2dd52c237a4b560aaf9e75c202R128)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nvazquez
when register a deploy-as-is template, the template NICs are not available until the template is downloaded successfully.
I think it is better that user configures VNF nics only when template NICs are fetched from OVA template.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…fTemplateManagerImpl.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…plate/VnfTemplateManagerImpl.java" This reverts commit 0bfc65a.
|
This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch. |
|
NOTE #12436 (comment) -> check tooltip fix while verifying this PR |
|
@blueorangutan package |
|
thanks @DaanHoogland @nvazquez can you please review ? thanks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Tests Execution Summary
| TC | Description | Status |
|---|---|---|
| TC1 | Deploy VNF via API | PASSED |
| TC2 | Deploy VNF via UI | PASSED |
| TC3 | Register deploy-as-is without VNF NICs | PASSED |
| TC4 | Register deploy-as-is with VNF NICs (negative) | PASSED |
| TC5 | Update deploy-as-is template with VNF NICs | PASSED |
| TC6 | UI network selection behavior | PASSED |
| TC7 | Deploy with all NICs mapped correctly | PASSED |
| TC8 | Deploy with missing NIC mapping | PASSED |
| TC9 | Verify VNF functionality post-deploy | PASSED |
| TC10 | Multiple deployments from same template | PASSED |
| TC11 | Regression – regular VNF template | PASSED |
Result: 11/11 test cases PASSED.
Environment
CloudStack: 4.20.3.0-SNAPSHOT (PR #12499)
Hypervisor: VMware
Template: Cisco ASAv OVA (10 NICs)
Key Findings
- Main bug fixed: Deploy-as-is VNF templates now deploy successfully via nicnetworklist parameter
- NIC mapping: nicnetworklist[X].nic must use OVA InstanceID values (e.g., 6, 9, 10...), not sequential device IDs
- Auto-fill behavior: Unspecified NICs are auto-filled with zone's default network (intentional design)
- No regression: Regular VNF templates still work with networkids parameter
Separate Issue Found
Bug #12510: This is a separate UI bug, not related to PR #12499
**Workaround: ** Deploy via CloudMonkey CLI with properties[0].key=HARole properties[0].value=Standalone
Detailed Test Results
TC1: Deploy VNF Appliance via Deploy-as-is Template (Main Bug Fix)
Objective: Verify the original bug is fixed - deploying VNF appliance using deploy-as-is template no longer fails with "VNF nics list is empty"
Expected Result: VM deploys successfully without "VNF nics list is empty" error
Actual Result: PASSED - VM ID: 4d319d1f-8de8-4b05-84ba-8b580d731ca5, State: Running, 10 NICs created
Test Evidence:
(localcloud) 🐱 > deployVnfAppliance templateid=88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd serviceofferingid=63b6851c-631c-4b30-81f0-e959e2eb6052 zoneid=e9594751-da68-4f49-924f-222ba4c15876 nicnetworklist[0].nic=0 nicnetworklist[0].network=4935f651-04b5-49f7-b25a-55c6151ad5cb name=vnf-tc1-full properties[0].key=HARole properties[0].value=Standalone
{
"virtualmachine": {
"account": "admin",
"affinitygroup": [],
"arch": "x86_64",
"cpunumber": 1,
"cpuspeed": 500,
"created": "2026-01-23T08:22:14+0000",
"deleteprotection": false,
"details": {
"cpuOvercommitRatio": "2.0",
"dataDiskController": "osdefault",
"rootDiskController": "lsilogic"
},
"displayname": "vnf-tc1-full",
"displayvm": true,
"domain": "ROOT",
"domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
"domainpath": "/",
"guestosid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
"haenable": false,
"hasannotations": false,
"hostcontrolstate": "Enabled",
"hostid": "cfcf5c46-b2dc-4c40-b487-eb8a111a83b3",
"hostname": "10.0.35.172",
"hypervisor": "VMware",
"id": "4d319d1f-8de8-4b05-84ba-8b580d731ca5",
"instancename": "i-2-7-VM",
"ipaddress": "10.1.1.52",
"isdynamicallyscalable": false,
"jobid": "4db54012-7faa-4eb0-833f-8eac824d7b27",
"jobstatus": 0,
"lastupdated": "2026-01-23T08:24:11+0000",
"memory": 512,
"name": "vnf-tc1-full",
"nic": [
{
"broadcasturi": "vlan://1161",
"deviceid": "2",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "a46379db-2c9b-4656-bfb5-bfd99adb366a",
"ipaddress": "10.1.1.114",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:18",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "8",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "f7e2761b-73f0-4f67-99ba-fc663695d863",
"ipaddress": "10.1.1.185",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:1e",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "4",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "9e609129-55c8-4ed5-bb84-35a27fc39deb",
"ipaddress": "10.1.1.197",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:1a",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "9",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "ccc16eb3-9e07-47f5-9dc2-faed9afd7eb6",
"ipaddress": "10.1.1.137",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:1f",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "7",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "0afd124b-8c07-4db5-bdc0-b2858043ceea",
"ipaddress": "10.1.1.38",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:1d",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "3",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "9176d2c0-a91e-4c3e-8ca1-207a3b792475",
"ipaddress": "10.1.1.240",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:19",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "6",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "fbf965f5-ec8e-4806-a514-7f3b520a2b66",
"ipaddress": "10.1.1.150",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:1c",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "0",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "ca0d01fe-4696-472b-8923-2961ee65edc3",
"ipaddress": "10.1.1.52",
"isdefault": true,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:16",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "1",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "9017b11f-b315-4812-82bb-b8b1a3d3a682",
"ipaddress": "10.1.1.202",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:17",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "5",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "e9f8916a-ba2d-4d95-a667-dce690ace4aa",
"ipaddress": "10.1.1.81",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:1b",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
}
],
"osdisplayname": "Other 2.6x Linux (64-bit)",
"ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
"passwordenabled": false,
"pooltype": "PreSetup",
"receivedbytes": 0,
"rootdeviceid": 0,
"rootdevicetype": "ROOT",
"securitygroup": [],
"sentbytes": 0,
"serviceofferingid": "63b6851c-631c-4b30-81f0-e959e2eb6052",
"serviceofferingname": "Small Instance",
"state": "Running",
"tags": [],
"templatedisplaytext": "ASAv VNF deploy-as-is test",
"templateformat": "OVA",
"templateid": "88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd",
"templatename": "ASAv-VNF-test-vnf",
"templatetype": "VNF",
"userid": "1095c455-f7cd-11f0-bc70-1e00b6000327",
"username": "admin",
"zoneid": "e9594751-da68-4f49-924f-222ba4c15876",
"zonename": "ref-trl-10698-v-Mol8-rositsa-kyuchukova"
}
}TC2 (UI): Deploy VNF Appliance via UI with Deploy-as-is Template
Objective: Verify the original bug is fixed via UI - Deploy VNF Appliance wizard works with deploy-as-is templates
Expected Result: VM deploys successfully via UI without "VNF nics list is empty" error
Actual Result: PASSED - VM created with 10 NICs properly mapped to networks
Test Evidence:
- Deploying via UI
Screencast.from.2026-01-23.10-43-23.webm
- Launching VNF appliance
NOTE Identified a separate UI bug, while executing this test case: #12510
TC3: Register Deploy-as-is VNF Template WITHOUT VNF Nics
Objective: Verify registering a deploy-as-is VNF template without specifying VNF nics succeeds
Expected Result: Template registers successfully; VNF nics read from OVA after download
Actual Result: PASSED - Template ID: 3dc7c5e0-46ad-4531-a8e4-149461be237f, Status: Ready, 10 NICs auto-populated from OVA
Test Evidence:
(localcloud) 🐱 > listVnfTemplates id=3dc7c5e0-46ad-4531-a8e4-149461be237f templatefilter=all filter=id,name,status,isready,templatetype,deployasis
{
"count": 1,
"template": [
{
"deployasis": true,
"id": "3dc7c5e0-46ad-4531-a8e4-149461be237f",
"isready": true,
"name": "vnf-tc3-no-nics",
"status": "Download Complete",
"templatetype": "VNF"
}
]
}
(localcloud) 🐱 >
TC4: Register Deploy-as-is VNF Template WITH VNF Nics (Negative Test)
Objective: Verify proper error when trying to register deploy-as-is template with VNF nics specified
Expected Result: Error rejecting VNF nics parameter for deploy-as-is templates
Actual Result: PASSED - Proper validation error returned
Test Evidence:
(localcloud) 🐱 > registerVnfTemplate name=vnf-tc4-with-nics displaytext="TC4 VNF with nics - should fail" format=OVA hypervisor=VMware ostypeid=cac8e8aa-f7cc-11f0-bc70-1e00b6000327 zoneid=e9594751-da68-4f49-924f-222ba4c15876 url=http://10.0.3.122/ova/asav951.ova deployasis=true vnfnics[0].deviceid=0 vnfnics[0].name=eth0 vnfnics[0].required=true
🙈 Error: (HTTP 431, error code 4350) VNF Template cannot be registered with VNF nics as Template settings are read from OVA.
TC5: Update Deploy-as-is VNF Template with VNF Nics
Objective: Verify updating deploy-as-is template to add VNF nics is allowed after template is ready
Expected Result: Update succeeds - user can configure VNF nics after OVA is downloaded
Actual Result: PASSED - VNF nics were added successfully
Test Evidence:
(localcloud) 🐱 > updateVnfTemplate id=3dc7c5e0-46ad-4531-a8e4-149461be237f vnfnics[0].deviceid=0 vnfnics[0].name=eth0 vnfnics[0].required=true
{
"template": {
"account": "admin",
"bits": 0,
"bootable": true,
"created": "2026-01-23T09:21:09+0000",
"crossZones": false,
"displaytext": "TC3 VNF without nics",
"domain": "ROOT",
"domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
"domainpath": "/",
"format": "OVA",
"hypervisor": "VMware",
"id": "3dc7c5e0-46ad-4531-a8e4-149461be237f",
"isdynamicallyscalable": false,
"isfeatured": false,
"ispublic": false,
"isready": false,
"name": "vnf-tc3-no-nics",
"ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
"ostypename": "Other 2.6x Linux (64-bit)",
"tags": [],
"templatetype": "VNF",
"vnfnics": [
{
"deviceid": 0,
"management": true,
"name": "eth0",
"required": true
}
]
}
}
TC6: UI - Network Selection Behavior for Deploy-as-is Template
Objective: Verify UI properly handles network selection for deploy-as-is templates
Expected Result: UI displays all OVA-defined NICs with functional network selection; no option to modify NIC definitions
Actual Result: PASSED - All 10 NICs from OVA displayed with correct names, "Change" button functional, no add/remove options
Evidence
TC7: Deploy VNF with All Required NICs Mapped
Objective: Verify deployment succeeds when all required NICs have networks assigned
Expected Result: Deployment succeeds; VM has correct network attachments matching the specified mapping
Actual Result: PARTIAL PASS / POTENTIAL BUG - VM deployed successfully with 10 NICs in Running state, but network mapping does not match the specified nicnetworklist parameter. Only 3/10 NICs attached to correct networks.
Test Evidence:
(localcloud) 🐱 > deployVnfAppliance templateid=88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd serviceofferingid=63b6851c-631c-4b30-81f0-e959e2eb6052 zoneid=e9594751-da68-4f49-924f-222ba4c15876 name=vnf-tc7-correct-ids properties[0].key=HARole properties[0].value=Standalone nicnetworklist[0].nic=6 nicnetworklist[0].network=4935f651-04b5-49f7-b25a-55c6151ad5cb nicnetworklist[1].nic=9 nicnetworklist[1].network=fee6a3ae-b99f-4ebe-b84b-c661fc4d5888 nicnetworklist[2].nic=10 nicnetworklist[2].network=a170136d-9699-4586-8eaf-f83f19255a54 nicnetworklist[3].nic=11 nicnetworklist[3].network=9427bebb-848d-4b54-8e22-06bfdcc83dcd nicnetworklist[4].nic=12 nicnetworklist[4].network=4935f651-04b5-49f7-b25a-55c6151ad5cb nicnetworklist[5].nic=13 nicnetworklist[5].network=fee6a3ae-b99f-4ebe-b84b-c661fc4d5888 nicnetworklist[6].nic=14 nicnetworklist[6].network=a170136d-9699-4586-8eaf-f83f19255a54 nicnetworklist[7].nic=15 nicnetworklist[7].network=9427bebb-848d-4b54-8e22-06bfdcc83dcd nicnetworklist[8].nic=16 nicnetworklist[8].network=4935f651-04b5-49f7-b25a-55c6151ad5cb nicnetworklist[9].nic=17 nicnetworklist[9].network=fee6a3ae-b99f-4ebe-b84b-c661fc4d5888
{
"virtualmachine": {
"account": "admin",
"affinitygroup": [],
"arch": "x86_64",
"cpunumber": 1,
"cpuspeed": 500,
"created": "2026-01-23T10:26:18+0000",
"deleteprotection": false,
"details": {
"cpuOvercommitRatio": "2.0",
"dataDiskController": "osdefault",
"rootDiskController": "lsilogic"
},
"displayname": "vnf-tc7-correct-ids",
"displayvm": true,
"domain": "ROOT",
"domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
"domainpath": "/",
"guestosid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
"haenable": false,
"hasannotations": false,
"hostcontrolstate": "Enabled",
"hostid": "7a9c02a7-19f8-46a1-9ef3-a4ff7fe90ba6",
"hostname": "10.0.35.255",
"hypervisor": "VMware",
"id": "3093cba4-9238-44f7-a5d4-198e4df0cad6",
"instancename": "i-2-15-VM",
"ipaddress": "10.1.1.65",
"isdynamicallyscalable": false,
"jobid": "1cb3ca2e-9052-4e73-bf79-f0a569261530",
"jobstatus": 0,
"lastupdated": "2026-01-23T10:29:53+0000",
"memory": 512,
"name": "vnf-tc7-correct-ids",
"nic": [
{
"broadcasturi": "vlan://1175",
"deviceid": "5",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "54fd720d-aed4-47fa-aef3-2ec59541f9a9",
"ipaddress": "10.1.1.27",
"isdefault": false,
"isolationuri": "vlan://1175",
"macaddress": "02:01:00:ce:00:07",
"netmask": "255.255.255.0",
"networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
"networkname": "vnf-net2",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1175",
"deviceid": "9",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "c3473e84-b1d3-4de3-93c2-5144dc48e683",
"ipaddress": "10.1.1.32",
"isdefault": false,
"isolationuri": "vlan://1175",
"macaddress": "02:01:00:ce:00:08",
"netmask": "255.255.255.0",
"networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
"networkname": "vnf-net2",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1179",
"deviceid": "8",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "9181e5aa-7b27-47fc-9095-4eca7a4138c7",
"ipaddress": "10.1.1.201",
"isdefault": false,
"isolationuri": "vlan://1179",
"macaddress": "02:01:00:cd:00:07",
"netmask": "255.255.255.0",
"networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
"networkname": "vnf-net1",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1164",
"deviceid": "2",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "e6be4593-cc05-422d-a768-2702bdf64806",
"ipaddress": "10.1.1.98",
"isdefault": false,
"isolationuri": "vlan://1164",
"macaddress": "02:01:00:cf:00:06",
"netmask": "255.255.255.0",
"networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
"networkname": "vnf-net3",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1179",
"deviceid": "0",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "eb098621-fbe9-4914-a74e-656fbcc3eff9",
"ipaddress": "10.1.1.65",
"isdefault": true,
"isolationuri": "vlan://1179",
"macaddress": "02:01:00:cd:00:05",
"netmask": "255.255.255.0",
"networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
"networkname": "vnf-net1",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1164",
"deviceid": "6",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "3ae4f2e9-9b87-4b81-b988-1dfff6b62765",
"ipaddress": "10.1.1.72",
"isdefault": false,
"isolationuri": "vlan://1164",
"macaddress": "02:01:00:cf:00:07",
"netmask": "255.255.255.0",
"networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
"networkname": "vnf-net3",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1179",
"deviceid": "4",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "3a78494a-d496-4cd7-a899-610d85a917d5",
"ipaddress": "10.1.1.27",
"isdefault": false,
"isolationuri": "vlan://1179",
"macaddress": "02:01:00:cd:00:06",
"netmask": "255.255.255.0",
"networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
"networkname": "vnf-net1",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "7",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "3e6a983f-5e01-4859-93ac-0c57a6d8e7dc",
"ipaddress": "10.1.1.160",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:3e",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1175",
"deviceid": "1",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "34a285a4-f3f4-4314-80aa-376a194b8abf",
"ipaddress": "10.1.1.162",
"isdefault": false,
"isolationuri": "vlan://1175",
"macaddress": "02:01:00:ce:00:06",
"netmask": "255.255.255.0",
"networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
"networkname": "vnf-net2",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "3",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "9236a428-b995-4866-918a-0257ada77b09",
"ipaddress": "10.1.1.229",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:3d",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
}
],
"osdisplayname": "Other 2.6x Linux (64-bit)",
"ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
"passwordenabled": false,
"pooltype": "PreSetup",
"receivedbytes": 0,
"rootdeviceid": 0,
"rootdevicetype": "ROOT",
"securitygroup": [],
"sentbytes": 0,
"serviceofferingid": "63b6851c-631c-4b30-81f0-e959e2eb6052",
"serviceofferingname": "Small Instance",
"state": "Running",
"tags": [],
"templatedisplaytext": "ASAv VNF deploy-as-is test",
"templateformat": "OVA",
"templateid": "88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd",
"templatename": "ASAv-VNF-test-vnf",
"templatetype": "VNF",
"userid": "1095c455-f7cd-11f0-bc70-1e00b6000327",
"username": "admin",
"zoneid": "e9594751-da68-4f49-924f-222ba4c15876",
"zonename": "ref-trl-10698-v-Mol8-rositsa-kyuchukova"
}
}- VNF Appliance deployed, in a Running state
(localcloud) 🐱 > listVirtualMachines name=vnf-tc7-correct-ids filter=id,name,state,nic
{
"count": 1,
"virtualmachine": [
{
"id": "3093cba4-9238-44f7-a5d4-198e4df0cad6",
"name": "vnf-tc7-correct-ids",
"nic": [
{
"broadcasturi": "vlan://1179",
"deviceid": "0",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "eb098621-fbe9-4914-a74e-656fbcc3eff9",
"ipaddress": "10.1.1.65",
"isdefault": true,
"isolationuri": "vlan://1179",
"macaddress": "02:01:00:cd:00:05",
"netmask": "255.255.255.0",
"networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
"networkname": "vnf-net1",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1175",
"deviceid": "1",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "34a285a4-f3f4-4314-80aa-376a194b8abf",
"ipaddress": "10.1.1.162",
"isdefault": false,
"isolationuri": "vlan://1175",
"macaddress": "02:01:00:ce:00:06",
"netmask": "255.255.255.0",
"networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
"networkname": "vnf-net2",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1164",
"deviceid": "2",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "e6be4593-cc05-422d-a768-2702bdf64806",
"ipaddress": "10.1.1.98",
"isdefault": false,
"isolationuri": "vlan://1164",
"macaddress": "02:01:00:cf:00:06",
"netmask": "255.255.255.0",
"networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
"networkname": "vnf-net3",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "3",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "9236a428-b995-4866-918a-0257ada77b09",
"ipaddress": "10.1.1.229",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:3d",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1179",
"deviceid": "4",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "3a78494a-d496-4cd7-a899-610d85a917d5",
"ipaddress": "10.1.1.27",
"isdefault": false,
"isolationuri": "vlan://1179",
"macaddress": "02:01:00:cd:00:06",
"netmask": "255.255.255.0",
"networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
"networkname": "vnf-net1",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1175",
"deviceid": "5",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "54fd720d-aed4-47fa-aef3-2ec59541f9a9",
"ipaddress": "10.1.1.27",
"isdefault": false,
"isolationuri": "vlan://1175",
"macaddress": "02:01:00:ce:00:07",
"netmask": "255.255.255.0",
"networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
"networkname": "vnf-net2",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1164",
"deviceid": "6",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "3ae4f2e9-9b87-4b81-b988-1dfff6b62765",
"ipaddress": "10.1.1.72",
"isdefault": false,
"isolationuri": "vlan://1164",
"macaddress": "02:01:00:cf:00:07",
"netmask": "255.255.255.0",
"networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
"networkname": "vnf-net3",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "7",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "3e6a983f-5e01-4859-93ac-0c57a6d8e7dc",
"ipaddress": "10.1.1.160",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:3e",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1179",
"deviceid": "8",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "9181e5aa-7b27-47fc-9095-4eca7a4138c7",
"ipaddress": "10.1.1.201",
"isdefault": false,
"isolationuri": "vlan://1179",
"macaddress": "02:01:00:cd:00:07",
"netmask": "255.255.255.0",
"networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
"networkname": "vnf-net1",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1175",
"deviceid": "9",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "c3473e84-b1d3-4de3-93c2-5144dc48e683",
"ipaddress": "10.1.1.32",
"isdefault": false,
"isolationuri": "vlan://1175",
"macaddress": "02:01:00:ce:00:08",
"netmask": "255.255.255.0",
"networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
"networkname": "vnf-net2",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
}
],
"state": "Running"
}
]
}Network Mapping Verification:
| Device ID | Actual Network | Expected Network | Status |
|---|---|---|---|
| 0 | vnf-net1 | vnf-net1 | PASS |
| 1 | vnf-net2 | vnf-net2 | PASS |
| 2 | vnf-net3 | vnf-net3 | PASS |
| 3 | test | test | PASS |
| 4 | vnf-net1 | vnf-net1 | PASS |
| 5 | vnf-net2 | vnf-net2 | PASS |
| 6 | vnf-net3 | vnf-net3 | PASS |
| 7 | test | test | PASS |
| 8 | vnf-net1 | vnf-net1 | PASS |
| 9 | vnf-net2 | vnf-net2 | PASS |
Key Finding: The nicnetworklist[X].nic parameter must use the OVA's InstanceID values (6, 9, 10, 11, 12, 13, 14, 15, 16, 17), NOT sequential device IDs (0-9). The UI handles this correctly by reading the InstanceIDs from the template's deployasisdetails. When using the API directly, users must reference the correct InstanceID values from the OVA template.
TC8: Deploy VNF with Missing Required NIC Mapping
Objective: Verify behavior when not all NICs are mapped in the nicnetworklist parameter
Expected Result: Auto-fill
Actual Result: PASSED - Deployment succeeded. Unspecified NICs were auto-filled with the zone's default network (intentional design confirmed via code analysis)
Test Evidence:
(localcloud) 🐱 > deployVnfAppliance templateid=88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd serviceofferingid=63b6851c-631c-4b30-81f0-e959e2eb6052 zoneid=e9594751-da68-4f49-924f-222ba4c15876 name=vnf-tc8-missing-nics properties[0].key=HARole properties[0].value=Standalone nicnetworklist[0].nic=6 nicnetworklist[0].network=4935f651-04b5-49f7-b25a-55c6151ad5cb nicnetworklist[1].nic=9 nicnetworklist[1].network=fee6a3ae-b99f-4ebe-b84b-c661fc4d5888 nicnetworklist[2].nic=10 nicnetworklist[2].network=a170136d-9699-4586-8eaf-f83f19255a54 nicnetworklist[3].nic=11 nicnetworklist[3].network=9427bebb-848d-4b54-8e22-06bfdcc83dcd nicnetworklist[4].nic=12 nicnetworklist[4].network=4935f651-04b5-49f7-b25a-55c6151ad5cb
{
"virtualmachine": {
"account": "admin",
"affinitygroup": [],
"arch": "x86_64",
"cpunumber": 1,
"cpuspeed": 500,
"created": "2026-01-23T10:44:25+0000",
"deleteprotection": false,
"details": {
"cpuOvercommitRatio": "2.0",
"dataDiskController": "osdefault",
"rootDiskController": "lsilogic"
},
"displayname": "vnf-tc8-missing-nics",
"displayvm": true,
"domain": "ROOT",
"domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
"domainpath": "/",
"guestosid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
"haenable": false,
"hasannotations": false,
"hostcontrolstate": "Enabled",
"hostid": "cfcf5c46-b2dc-4c40-b487-eb8a111a83b3",
"hostname": "10.0.35.172",
"hypervisor": "VMware",
"id": "a7268a53-e778-43f3-a3a4-b6b3038f0b22",
"instancename": "i-2-16-VM",
"ipaddress": "10.1.1.89",
"isdynamicallyscalable": false,
"jobid": "f08e5467-0221-4ae7-8331-cdeb8d696e66",
"jobstatus": 0,
"lastupdated": "2026-01-23T10:45:02+0000",
"memory": 512,
"name": "vnf-tc8-missing-nics",
"nic": [
{
"broadcasturi": "vlan://1179",
"deviceid": "0",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "b6473fb5-c9d8-4c82-b3db-45922f23e74f",
"ipaddress": "10.1.1.89",
"isdefault": true,
"isolationuri": "vlan://1179",
"macaddress": "02:01:00:cd:00:08",
"netmask": "255.255.255.0",
"networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
"networkname": "vnf-net1",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "3",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "4b15b3ac-a784-4e04-8f51-650091f4f85e",
"ipaddress": "10.1.1.199",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:3f",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "7",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "8009e199-db72-4f3b-a33d-c85668a7cd47",
"ipaddress": "10.1.1.35",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:42",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "9",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "dd193817-d83e-4ea3-8963-cde90b546c2e",
"ipaddress": "10.1.1.218",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:44",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1164",
"deviceid": "2",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "45c08e6a-7158-440c-a2b8-ea8298087174",
"ipaddress": "10.1.1.245",
"isdefault": false,
"isolationuri": "vlan://1164",
"macaddress": "02:01:00:cf:00:08",
"netmask": "255.255.255.0",
"networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
"networkname": "vnf-net3",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "5",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "5569f400-f0d4-485c-ab5f-6189f2fe18b8",
"ipaddress": "10.1.1.85",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:40",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1179",
"deviceid": "4",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "39c9d26e-ffdc-4129-953d-adec5482ca7d",
"ipaddress": "10.1.1.12",
"isdefault": false,
"isolationuri": "vlan://1179",
"macaddress": "02:01:00:cd:00:09",
"netmask": "255.255.255.0",
"networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
"networkname": "vnf-net1",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1175",
"deviceid": "1",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "dfe7e980-8705-4b2f-a55a-6320883a6d3c",
"ipaddress": "10.1.1.18",
"isdefault": false,
"isolationuri": "vlan://1175",
"macaddress": "02:01:00:ce:00:09",
"netmask": "255.255.255.0",
"networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
"networkname": "vnf-net2",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "8",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "0d509279-8d6a-44b2-805f-beb50d44e151",
"ipaddress": "10.1.1.241",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:43",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1161",
"deviceid": "6",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "da852d6e-551a-48c7-bfd6-e029f7dd4947",
"ipaddress": "10.1.1.47",
"isdefault": false,
"isolationuri": "vlan://1161",
"macaddress": "02:01:00:cc:00:41",
"netmask": "255.255.255.0",
"networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
"networkname": "test",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
}
],
"osdisplayname": "Other 2.6x Linux (64-bit)",
"ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
"passwordenabled": false,
"pooltype": "PreSetup",
"receivedbytes": 0,
"rootdeviceid": 0,
"rootdevicetype": "ROOT",
"securitygroup": [],
"sentbytes": 0,
"serviceofferingid": "63b6851c-631c-4b30-81f0-e959e2eb6052",
"serviceofferingname": "Small Instance",
"state": "Running",
"tags": [],
"templatedisplaytext": "ASAv VNF deploy-as-is test",
"templateformat": "OVA",
"templateid": "88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd",
"templatename": "ASAv-VNF-test-vnf",
"templatetype": "VNF",
"userid": "1095c455-f7cd-11f0-bc70-1e00b6000327",
"username": "admin",
"zoneid": "e9594751-da68-4f49-924f-222ba4c15876",
"zonename": "ref-trl-10698-v-Mol8-rositsa-kyuchukova"
}
}| Device ID | Specified? | Actual Network |
|---|---|---|
| 0 | Yes (nic=6 → vnf-net1) | vnf-net1 |
| 1 | Yes (nic=9 → vnf-net2) | vnf-net2 |
| 2 | Yes (nic=10 → vnf-net3) | vnf-net3 |
| 3 | Yes (nic=11 → test) | test |
| 4 | Yes (nic=12 → vnf-net1) | vnf-net1 |
| 5 | No (Not specified) | test (auto-filled) |
| 6 | No (Not specified) | test (auto-filled) |
| 7 | No (Not specified) | test (auto-filled) |
| 8 | No (Not specified) | test (auto-filled) |
| 9 | No (Not specified) | test (auto-filled) |
Code Analysis: Auto-fill is intentional, implemented in UserVmManagerImpl.getVmOvfNetworkMapping() - unspecified NICs receive the zone's default network.
TC9: Verify VNF Appliance Functionality Post-Deploy
Objective: Verify deployed VNF appliance is functional
Expected Result: VM runs with correct network configuration matching the deployment specification
Actual Result: PASSED - All 10 NICs correctly mapped to expected networks, VM status Running
Test Evidence:
- CloudStack UI - VNF Appliances - vnf-tc7-correct-ids - NICs tab showing all 10 NICs with correct network mappings
TC10: Deploy Multiple VNF Appliances from Same Template
Objective: Verify template can be used for multiple deployments
Expected Result: Multiple VMs can be deployed from the same template
**Actual Result: **PASSED - 7 VMs deployed from the same template, 4 Running successfully
Test Evidence:
(localcloud) 🐱 > listVirtualMachines templateid=88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd filter=id,name,state
{
"count": 7,
"virtualmachine": [
{
"id": "4d319d1f-8de8-4b05-84ba-8b580d731ca5",
"name": "vnf-tc1-full-api",
"state": "Running"
},
{
"id": "6d0f73d2-8e3c-474f-9223-2886c15e2cb2",
"name": "VM-6d0f73d2-8e3c-474f-9223-2886c15e2cb2",
"state": "Error"
},
{
"id": "46f2bd49-ea2f-4e78-b8df-32510022b955",
"name": "vnf-ui-test2",
"state": "Error"
},
{
"id": "a1593da3-fd58-494a-9e4e-977f8f24047c",
"name": "vnf-ui-test3",
"state": "Error"
},
{
"id": "92b72388-5fcc-4469-9a28-e24b794b2cd2",
"name": "vnf-tc7-mixed-networks",
"state": "Running"
},
{
"id": "3093cba4-9238-44f7-a5d4-198e4df0cad6",
"name": "vnf-tc7-correct-ids",
"state": "Running"
},
{
"id": "a7268a53-e778-43f3-a3a4-b6b3038f0b22",
"name": "vnf-tc8-missing-nics",
"state": "Running"
}
]
}
| Deployment Method | Count | Status |
|---|---|---|
| API (with properties) | 4 | Running |
| UI (without properties – bug #12510) | 3 | Error |
Note: The 3 VMs in Error state are due to UI bug #12510 (vApp properties are not sent), not an issue with multiple deployments.
TC11: Regular (non-deploy-as-is) VNF Template Still Works
Objective: Regression test - ensure regular VNF templates still function after PR changes
Expected Result: Existing VNF template functionality unchanged - deployment using networkids parameter works
Actual Result: PASSED - VM deployed successfully with 2 NICs correctly mapped using networkids parameter
Test Evidence:
- regular VNF template
(localcloud) 🐱 > listVnfTemplates id=117856e5-6d81-40d9-bd77-7b3f1a706435 templatefilter=all filter=id,name,isready,status
{
"count": 1,
"template": [
{
"id": "117856e5-6d81-40d9-bd77-7b3f1a706435",
"isready": true,
"name": "vnf-tc11-regular",
"status": "Download Complete"
}
]
}
- appliance deployed successfully with the regular VNF template
(localcloud) 🐱 > deployVnfAppliance templateid=117856e5-6d81-40d9-bd77-7b3f1a706435 serviceofferingid=63b6851c-631c-4b30-81f0-e959e2eb6052 zoneid=e9594751-da68-4f49-924f-222ba4c15876 name=vnf-tc11-regular-deploy networkids=4935f651-04b5-49f7-b25a-55c6151ad5cb,fee6a3ae-b99f-4ebe-b84b-c661fc4d5888
{
"virtualmachine": {
"account": "admin",
"affinitygroup": [],
"arch": "x86_64",
"cpunumber": 1,
"cpuspeed": 500,
"created": "2026-01-23T12:00:29+0000",
"deleteprotection": false,
"details": {
"cpuOvercommitRatio": "2.0",
"dataDiskController": "lsilogic",
"dataDiskControllervmdisk2": "lsilogic",
"rootDiskController": "ide"
},
"displayname": "vnf-tc11-regular-deploy",
"displayvm": true,
"domain": "ROOT",
"domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
"domainpath": "/",
"guestosid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
"haenable": false,
"hasannotations": false,
"hostcontrolstate": "Enabled",
"hostid": "cfcf5c46-b2dc-4c40-b487-eb8a111a83b3",
"hostname": "10.0.35.172",
"hypervisor": "VMware",
"id": "6e78683a-f8d9-4c15-84c8-53fd72f337ed",
"instancename": "i-2-17-VM",
"ipaddress": "10.1.1.31",
"isdynamicallyscalable": false,
"isodisplaytext": "day0.iso",
"isoid": "222b267d-0b28-4ce5-976d-6dfa6493aed5",
"isoname": "day0.iso",
"jobid": "9040d257-ea37-4cd1-9d2b-3866c898cec5",
"jobstatus": 0,
"lastupdated": "2026-01-23T12:01:07+0000",
"memory": 512,
"name": "vnf-tc11-regular-deploy",
"nic": [
{
"broadcasturi": "vlan://1175",
"deviceid": "1",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "0ca0727f-e737-4ee2-9343-41837b2445b3",
"ipaddress": "10.1.1.254",
"isdefault": false,
"isolationuri": "vlan://1175",
"macaddress": "02:01:00:ce:00:0a",
"netmask": "255.255.255.0",
"networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
"networkname": "vnf-net2",
"publicip": "10.0.52.188",
"publicipid": "0ac05a28-6a86-476a-ae41-53e1162f9396",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
},
{
"broadcasturi": "vlan://1179",
"deviceid": "0",
"extradhcpoption": [],
"gateway": "10.1.1.1",
"id": "230e3d30-409e-40ce-81d1-31043d2ec66b",
"ipaddress": "10.1.1.31",
"isdefault": true,
"isolationuri": "vlan://1179",
"macaddress": "02:01:00:cd:00:0a",
"netmask": "255.255.255.0",
"networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
"networkname": "vnf-net1",
"publicip": "10.0.52.187",
"publicipid": "5f84bd0b-8c78-4cbe-96f4-16ed55320408",
"secondaryip": [],
"traffictype": "Guest",
"type": "Isolated"
}
],
"osdisplayname": "Other 2.6x Linux (64-bit)",
"ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
"passwordenabled": false,
"pooltype": "PreSetup",
"publicip": "10.0.52.187",
"publicipid": "5f84bd0b-8c78-4cbe-96f4-16ed55320408",
"receivedbytes": 0,
"rootdeviceid": 0,
"rootdevicetype": "ROOT",
"securitygroup": [],
"sentbytes": 0,
"serviceofferingid": "63b6851c-631c-4b30-81f0-e959e2eb6052",
"serviceofferingname": "Small Instance",
"state": "Running",
"tags": [],
"templatedisplaytext": "TC11 Regular VNF template",
"templateformat": "OVA",
"templateid": "117856e5-6d81-40d9-bd77-7b3f1a706435",
"templatename": "vnf-tc11-regular",
"templatetype": "VNF",
"userid": "1095c455-f7cd-11f0-bc70-1e00b6000327",
"username": "admin",
"vnfnics": [
{
"deviceid": 0,
"management": true,
"name": "management",
"required": true
},
{
"deviceid": 1,
"management": true,
"name": "wan",
"required": true
}
],
"zoneid": "e9594751-da68-4f49-924f-222ba4c15876",
"zonename": "ref-trl-10698-v-Mol8-rositsa-kyuchukova"
}
}| Device ID | VNF NIC Name (from template) | Network We Specified | Network VM Actually Got |
|---|---|---|---|
| 0 | management | vnf-net1 (1st in list) | vnf-net1 |
| 1 | wan | vnf-net2 (2nd in list) | vnf-net2 |
Description
This PR fixes #12186
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
How did you try to break this feature and the system with this change?